package main

import (
	"database/sql"
	"fmt"

	"github.com/pkg/errors"
)

type QueryError struct {
	err         error
	msg         string
	serviceName string
}

var ErrServiceUnuseful = errors.New("ServiceUnuseful")

func (e *QueryError) Unwrap() error {
	return e.err
}

func (e *QueryError) Error() string {
	return fmt.Sprintf("service:%s, msg:%s", e.serviceName, e.msg)
}

func scan(dest ...interface{}) error {
	return sql.ErrNoRows
}

func DaoOperation(dest interface{}) error {
	err := scan(&dest)
	if err != nil {
		return errors.Wrap(err, "DaoOperation Failed")
	}
	return nil
}

func SomethingService() error {
	dest := ""
	if err := DaoOperation(&dest); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			dest = "NULL"
		} else {
			return errors.WithMessage(err, "SomethingService Failed")
		}
	}
	fmt.Printf("Service Success, dest=%s", dest)
	return nil
}

func Controller() error {
	err := SomethingService()
	if err != nil {
		fmt.Printf("service error: %+v", err)
		return &QueryError{serviceName: "SomethingSercie", msg: "Internel Error"}
	}
	return nil
}

func main() {
	err := Controller()
	responseCode := 200
	if err != nil {
		if errors.As(err, ErrServiceUnuseful) {
			responseCode = 500
		}
		responseCode = 400
	}
	fmt.Printf("Controller Response Code: %d", responseCode)
}
